package top.archiesean.common.security.config;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import top.archiesean.common.security.component.CustomBearerTokenResolver;
import top.archiesean.common.security.component.CustomOpaqueTokenIntrospector;
import top.archiesean.common.security.component.ResourceAuthExceptionEntryPoint;
import top.archiesean.common.security.properties.PermitAllUrlProperties;

/**
 * @author ArchieSean
 * @description 资源服务器配置
 * @date 2024-01-09 08:24
 */
@Slf4j
@EnableWebSecurity
@EnableMethodSecurity
@RequiredArgsConstructor
public class ResourceServerConfiguration {


    /**
     * 不鉴权路径配置文件
     */
    private final PermitAllUrlProperties urlProperties;

    /**
     * 自定义token拦截器
     */
    private final CustomOpaqueTokenIntrospector customOpaqueTokenIntrospector;

    /**
     * 认证异常处理
     */
    private final ResourceAuthExceptionEntryPoint resourceAuthExceptionEntryPoint;
    /**
     * 自定义basic令牌解析
     */
    private final CustomBearerTokenResolver customBearerTokenResolver;


    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        AntPathRequestMatcher[] matchers = urlProperties.getUrls()
                .stream()
                .map(AntPathRequestMatcher::new)
                .toList()
                .toArray(new AntPathRequestMatcher[]{});

        http.authorizeHttpRequests(authorize ->
                        authorize.requestMatchers(matchers)
                                .permitAll()
                                .anyRequest().authenticated()
                )
                .oauth2ResourceServer(oauth2 ->
                        //不透明token解析
                        oauth2.opaqueToken(token -> token.introspector(customOpaqueTokenIntrospector))
                                .authenticationEntryPoint(resourceAuthExceptionEntryPoint)
                                //basic 认证解析
                                .bearerTokenResolver(customBearerTokenResolver)
                )
                .headers(headers -> headers.frameOptions(HeadersConfigurer.FrameOptionsConfig::disable))
                .csrf(AbstractHttpConfigurer::disable)
        ;
        return http.build();
    }
}
